import { BlurRadiusMaterial } from '@/modules/threeMaterials';
import { BlurCircle } from '@/modules/threeMeshs';
import * as THREE from 'three';
import TWEEN from '@tweenjs/tween.js';
import { Line2 } from 'threeJsm/lines/Line2.js';
// const Line = require('threeJsm/lines/Line2.js')
import { LineGeometry } from 'threeJsm/lines/LineGeometry.js';
// const lineGeo = require('threeJsm/lines/LineGeometry.js')
import { LineMaterial } from 'threeJsm/lines/LineMaterial.js';

export class FlightGroup extends THREE.Group {
  STATUS: 0 | 1 | 2 = 0;
  flight: any; // 飞机
  start: any; // Vector3
  end: any; // Vector3
  distance: number;
  controlPoint: any; // Vector3
  curveLine: any; // LineCurve3
  // group:any;
  speed: number = 5;
  curveLength: number = 0;
  startMesh: any;
  endMesh: any;

  constructor(config: { start: any; end: any; flightMesh: any }) {
    super();
    this.start = config.start;
    this.end = config.end;
    this.distance = this.start.distanceTo(this.end);
    const sub = this.end.clone().sub(this.start);
    this.controlPoint = this.start
      .clone()
      .add(sub.multiplyScalar(0.5))
      .normalize()
      .multiplyScalar(this.start.length() + this.distance * 0.65);

    if (this.distance < 45 && this.distance > 8) {
      this.STATUS = 1;
      // this.group = new THREE.Group();
      this.initCurve();
      this.initPoint();
      this.initFlight(config.flightMesh);
    }
  }

  initCurve() {
    this.curveLine = new THREE.QuadraticBezierCurve3(
      this.start,
      this.controlPoint,
      this.end,
    );
    this.curveLength = this.curveLine.getLength();
    this.timeMax = this.curveLength ? this.curveLength / this.speed : 0;

    const points = this.curveLine.getPoints(50);
    const geometry = new THREE.BufferGeometry().setFromPoints(points);

    const material = new THREE.LineBasicMaterial({
      color: 0xffffff,
      transparent: true,
      opacity: 0.6,
      // linewidth: 4,
      // vertexColors: true,
    });

    // Create the final object to add to the scene
    const curveObject = new THREE.Line(geometry, material);
    this.add(curveObject);
  }

  initMeshCurve() {
    //有粗细的Mesh曲线
    this.curveLine = new THREE.QuadraticBezierCurve3(
      this.start,
      this.controlPoint,
      this.end,
    );

    const points = this.curveLine.getPoints(50);

    let positions = [],
      colors = [];
    const color = new THREE.Color('#ffffff');
    for (let i = 0; i < points.length; i++) {
      const point = points[i];
      positions.push(point.x, point.y, point.z);
      colors.push(color.r, color.g, color.b);
    }
    const lineGeometry = new LineGeometry();
    lineGeometry.setPositions(positions);
    lineGeometry.setColors(colors);
    const matLine = new LineMaterial({
      color: 0xffffff,
      linewidth: 0.4, // in world units with size attenuation, pixels otherwise
      worldUnits: true,
      vertexColors: true,

      //resolution:  // to be set by renderer, eventually
      alphaToCoverage: true,
    });
    const line = new Line2(lineGeometry, matLine);
    this.add(line);
  }

  initPoint() {
    const geometry = new THREE.IcosahedronGeometry(0.4, 1);
    const material = new THREE.MeshLambertMaterial({ color: 0xff8a43 });
    // const material = new LumenSideMaterial( {
    //   viewVector: this.camera.position.clone().sub(this.controls.target),
    //   glowColor: '#fff',
    //   bias: 1, power: 4.5, scale: -0.7
    // });
    this.startMesh = new THREE.Mesh(geometry, material);
    this.startMesh.position.copy(this.start);
    this.startMesh.scale.set(0, 0, 0);
    this.startMesh.lookAt(new THREE.Vector3(0, 0, 0));

    const geometry2 = new THREE.TorusGeometry(0.7, 0.1, 7, 6);
    // const material2 = new THREE.MeshBasicMaterial({ color: 0xfe1212 });
    const material2 = new THREE.MeshLambertMaterial({ color: 0xb2daea });
    // const material2 = new BlurRadiusMaterial({blur: 0.1, radius: 0.8,
    //     color1: '#ed18c2',
    //     color2: '#ffabee'
    // })
    this.endMesh = new THREE.Mesh(geometry2, material2);
    // this.endMesh = new BlurCircle({blur: 0.5, radius: 0.3, geoSize: 2,
    //   color1: '#9fead6',
    //   color2: '#d89ce8'
    // })
    this.endMesh.position.copy(this.end);
    this.endMesh.scale.set(0, 0, 0);
    this.endMesh.lookAt(new THREE.Vector3(0, 0, 0));
    this.add(this.startMesh, this.endMesh);
  }

  initFlight(obj: any) {
    //飞机
    if (obj && obj.isObject3D) {
      this.flight = obj;
    }
    if (!this.flight) {
      const geometry = new THREE.BoxGeometry(1, 1, 1);
      const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
      this.flight = new THREE.Mesh(geometry, material);
    }

    this.flight.position.copy(this.start);
    this.flight.scale.set(0, 0, 0);
    this.add(this.flight);

    this.initTween();
  }

  private initTween = () => {
    let tween = new TWEEN.Tween(this.startMesh.scale)
      .to({ x: 1, y: 1, z: 1 }, 1600)
      .start()
      .onComplete(() => {
        // this.STATUS = 2;
      });
    tween.easing(TWEEN.Easing.Elastic.Out);

    let tween1 = new TWEEN.Tween(this.flight.scale)
      .to({ x: 1, y: 1, z: 1 }, 1000)
      .delay(1000)
      .start()
      .onStart(() => {
        this.STATUS = 2;
      });
  };

  private changePosition = (t) => {
    if (!this.curveLine) {
      return;
    }
    const position = this.curveLine.getPointAt(t); // t: 当前点在线条上的位置百分比，后面计算
    this.flight.position.copy(position);

    //改变物体朝向
    const tangent = this.curveLine.getTangentAt(t);
    // const lookAtVec = tangent.add(position); // 位置向量和切线向量相加即为所需朝向的点向量
    const lookAtVec = position.clone().add(tangent); // 位置向量和切线向量相加即为所需朝向的点向量
    this.flight.up = position.clone().normalize();
    this.flight.lookAt(lookAtVec); //如果parent有rotation，lookAt会偏差
    // this.flight.lookAt(new THREE.Vector3(0,0,0));

    // this.flight.updateMatrix()
    // this.flight.matrixAutoUpdate = true;
    // this.flight.matrixWorldAutoUpdate = true
  };

  private callbackFun?: () => void;
  onCallback(fun: () => void) {
    this.callbackFun = fun;
  }

  private timeMax = 0;
  private timeDur = 0;
  update(delta: number) {
    // console.log(delta);

    if (this.timeMax && this.STATUS == 2) {
      this.timeDur += delta;
      if (this.timeDur > this.timeMax) {
        // this.timeDur = 0;
        this.STATUS = 0;
        this.callbackFun && this.callbackFun();
      }
      const t = this.timeDur / this.timeMax;
      this.changePosition(t);
      // this.changePosition(0.5);

      let endScale = (t - 0.7) / 0.2;
      endScale = endScale < 0 ? 0 : endScale;
      this.endMesh.scale.set(endScale, endScale, endScale);
      if (endScale > 0) {
        this.startMesh.scale.set(1 - endScale, 1 - endScale, 1 - endScale);
      }
    }
  }

  destroy() {
    this.removeFromParent();
    this.clear();
  }
}
